#include "serial.h"
#include <string.h>
#include <stdarg.h>

// 实例数组
Serial_t g_serials[2] = {0};

// 获取实例指针
static Serial_t* get_serial(SerialPort port) {
    if (port == SERIAL1) return &g_serials[0];
    if (port == SERIAL2) return &g_serials[1];
    return NULL;
}

// 获取 USART 指针
static USART_TypeDef* get_usart(SerialPort port) {
    return (port == SERIAL1) ? USART1 : USART2;
}

// GPIO 初始化
static void serial_gpio_init(SerialPort port) {
    GPIO_InitTypeDef GPIO_InitStructure;
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE);

    if (port == SERIAL1) {
        // PA9: TX, PA10: RX
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_Init(GPIOA, &GPIO_InitStructure);

        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
        GPIO_Init(GPIOA, &GPIO_InitStructure);

        RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
    }
    else if (port == SERIAL2) {
        // PA2: TX, PA3: RX
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_Init(GPIOA, &GPIO_InitStructure);

        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
        GPIO_Init(GPIOA, &GPIO_InitStructure);

        RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
    }
}

// 配置 USART
static void serial_usart_init(USART_TypeDef* usart, uint32_t baudrate) {
    USART_InitTypeDef USART_InitStructure;
    USART_InitStructure.USART_BaudRate = baudrate;
    USART_InitStructure.USART_WordLength = USART_WordLength_8b;
    USART_InitStructure.USART_StopBits = USART_StopBits_1;
    USART_InitStructure.USART_Parity = USART_Parity_No;
    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
    USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
    USART_Init(usart, &USART_InitStructure);
    USART_ITConfig(usart, USART_IT_RXNE, ENABLE);
	USART_Cmd(usart, ENABLE);
}

// NVIC 配置
static void serial_nvic_init(SerialPort port) {
    NVIC_InitTypeDef NVIC_InitStructure;
    uint8_t irq_channel, sub_priority;

    if (port == SERIAL1) {
        irq_channel = USART1_IRQn;
        sub_priority = 0;
    } else {
        irq_channel = USART2_IRQn;
        sub_priority = 1;  // 不同优先级避免冲突
    }

    NVIC_InitStructure.NVIC_IRQChannel = irq_channel;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = sub_priority;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
}

// ==================== Public API ====================

void serial_begin(SerialPort port, uint32_t baudrate) {
    Serial_t* serial = get_serial(port);
    if (!serial) return;

    serial->usart = get_usart(port);

	
	
	// 初始化硬件
    serial_gpio_init(port);
    serial_usart_init(serial->usart, baudrate);
    serial_nvic_init(port);

    // 清空缓冲区
    memset(serial->rx_buffer, 0, sizeof(serial->rx_buffer));
    serial->rx_head = 0;
    serial->rx_tail = 0;
    serial->buffer_full_flag = 0;
    serial->onByteReceived = NULL;
    serial->onByteMatched = NULL;
    serial->match_byte = '\n';
}

void serial_end(SerialPort port) {
    Serial_t* serial = get_serial(port);
    if (!serial) return;

    USART_Cmd(serial->usart, DISABLE);
    USART_ITConfig(serial->usart, USART_IT_RXNE, DISABLE);

    // 可选：关闭时钟
}

// 缓冲区操作
int serial_available(SerialPort port) {
    Serial_t* serial = get_serial(port);
    if (!serial) return 0;
    return (sizeof(serial->rx_buffer) + serial->rx_head - serial->rx_tail) % sizeof(serial->rx_buffer);
}

int serial_read(SerialPort port) {
    Serial_t* serial = get_serial(port);
    if (!serial || serial->rx_head == serial->rx_tail) {
        return -1;
    }

    uint8_t data = serial->rx_buffer[serial->rx_tail];
    serial->rx_tail = (serial->rx_tail + 1) % sizeof(serial->rx_buffer);
    serial->buffer_full_flag = 0;
    return data;
}


void serial_write(SerialPort port, uint8_t byte) {
    USART_TypeDef* usart;

    Serial_t* serial = get_serial(port);
    if (!serial) return;
	
	usart = serial->usart;
	// 等待 TXE：发送数据寄存器为空，可以写入新数据
    while (!(usart->SR & USART_SR_TXE)); 
	
    // 发送字节
    usart->DR = byte;
}

void serial_print(SerialPort port, const char* str) {
    while (*str) {
        serial_write(port, *str++);
    }
}

void serial_println(SerialPort port, const char* str) {
    serial_print(port, str);
    serial_write(port, '\r');
    serial_write(port, '\n');
}

void serial_printf(SerialPort port, const char* format, ...) {
    Serial_t* serial = get_serial(port);
    if (!serial) return;

    char buf[128];
    va_list args;
    va_start(args, format);
    vsnprintf(buf, sizeof(buf), format, args);
    va_end(args);
    serial_print(port, buf);
}

// 回调设置
void serial_onByteReceived(SerialPort port, SerialByteCallback callback) {
    Serial_t* serial = get_serial(port);
    if (serial) serial->onByteReceived = callback;
}

void serial_onByteMatched(SerialPort port, SerialMatchCallback callback, uint8_t match_byte) {
    Serial_t* serial = get_serial(port);
    if (serial) {
        serial->onByteMatched = callback;
        serial->match_byte = match_byte;
    }
}

// ==================== 中断服务函数 ====================

void USART1_IRQHandler(void) {
    Serial_t* serial = &g_serials[0];  // USART1
	// ✅ 检查 Overrun Error
    if (USART1->SR & USART_SR_ORE) {
		USART_ClearFlag(USART1, USART_FLAG_ORE);
    }
    if (USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) {
        uint8_t byte = USART_ReceiveData(USART1);
        uint32_t next_head = (serial->rx_head + 1) % sizeof(serial->rx_buffer);

        if (next_head != serial->rx_tail) {
            serial->rx_buffer[serial->rx_head] = byte;
            serial->rx_head = next_head;

            if (serial->onByteReceived) serial->onByteReceived(byte);
            if (serial->onByteMatched && byte == serial->match_byte) {
                serial->onByteMatched(byte);
            }
        } else {
            serial->buffer_full_flag = 1;  // 溢出
        }
        USART_ClearITPendingBit(USART1, USART_IT_RXNE);
    }
}

void USART2_IRQHandler(void) {
    Serial_t* serial = &g_serials[1];  // USART2
	if (USART2->SR & USART_SR_ORE) {
		USART_ClearFlag(USART2, USART_FLAG_ORE);
    }
    if (USART_GetITStatus(USART2, USART_IT_RXNE) != RESET) {
        uint8_t byte = USART_ReceiveData(USART2);
        uint32_t next_head = (serial->rx_head + 1) % sizeof(serial->rx_buffer);

        if (next_head != serial->rx_tail) {
            serial->rx_buffer[serial->rx_head] = byte;
            serial->rx_head = next_head;

            if (serial->onByteReceived) serial->onByteReceived(byte);
            if (serial->onByteMatched && byte == serial->match_byte) {
                serial->onByteMatched(byte);
            }
        } else {
            serial->buffer_full_flag = 1;
			
        }
        USART_ClearITPendingBit(USART2, USART_IT_RXNE);
    }
}

//重定向printf到串口1
#pragma import(__use_no_semihosting)             
//标准库需要的支持函数                 
struct __FILE 
{ 
	int handle; 

}; 

FILE __stdout;       
//定义_sys_exit()以避免使用半主机模式    
void _sys_exit(int x) 
{ 
	x = x; 
} 
//重定义fputc函数 
int fputc(int ch, FILE *f)
{      
	while((USART1->SR&0X40)==0);//循环发送,直到发送完毕   
    USART1->DR = (u8) ch;      
	return ch;
}
